#!/bin/bash
# set -e

CN_SHELL=~/cn_shell
ETCD_HOME=$CN_SHELL/software/etcd-v3.5.11-linux-amd64
step=0

# 定义集群节点域名以及监听的端口号
host_01="192.168.1.115"
host_02="192.168.1.116"
host_03="192.168.1.117"
host_ips=($host_01 $host_02 $host_03)

HOST_NAME_1="cn5"
HOST_NAME_2="cn6"
HOST_NAME_3="cn7"
host_names=($HOST_NAME_1 $HOST_NAME_2 $HOST_NAME_3)

CERT_HOME=$CN_SHELL/cfssl
CN_NAME="LORRY_ETCD"
CN_HOST_IP=$host_01
CN_HOST_NAME=$HOST_NAME_1

peer_listen_port=2380
client_listen_port=2379
cert_path=$CERT_HOME/server.pem
cacert_path=$CERT_HOME/ca.pem 
keyfile_path=$CERT_HOME/server-key.pem

client_cert_path=$CERT_HOME/client.pem
cacert_path=$CERT_HOME/ca.pem 
client_keyfile_path=$CERT_HOME/client-key.pem


root_password=root


etcd_node_names=("etcd-01" "etcd-02" "etcd-03");
# TODO 有待优化
etcd_node_indeies=(1 2 3)

echo "****************************************"
echo "******* Generate Certification *********"
echo "****************************************"

let step=step+1
echo "### 1.$step init CA by json file *********"
# 创建证书目录
mkdir -p $CERT_HOME
# 定位到证书目录
cd $CERT_HOME
cfssl print-defaults config > $CERT_HOME/ca-config.json
cfssl print-defaults csr > $CERT_HOME/ca-csr.json

((step++))
echo "### 1.$step generate CA config file: ca-config.json *********"
cat << EOF > $CERT_HOME/ca-config.json
{
    "signing": {
        "default": {
            "expiry": "43800h"
        },
        "profiles": {
            "server": {
                "expiry": "43800h",
                "usages": [
                    "signing",
                    "key encipherment",
                    "server auth",
					"client auth"
                ]
            },
            "client": {
                "expiry": "43800h",
                "usages": [
                    "signing",
                    "key encipherment",
                    "client auth"
                ]
            },
            "peer": {
                "expiry": "43800h",
                "usages": [
                    "signing",
                    "key encipherment",
                    "server auth",
                    "client auth"
                ]
            }
        }
    }
}
EOF

((step++))
echo "### 1.$step generate CSR config file *********"
cat << EOF > $CERT_HOME/ca-csr.json
{
    "CN": "My own CA",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "US",
            "L": "CA",
            "O": "My Company Name",
            "ST": "San Francisco",
            "OU": "Org Unit 1",
            "OU": "Org Unit 2"
        }
    ]
}
EOF

((step++))
echo "### 1.$step generate CA Certification *********"
cfssl gencert -initca $CERT_HOME/ca-csr.json | cfssljson -bare ca -

((step++))
echo "### 1.$step generate Certification *********"
echo '{"CN":"cn5","hosts":["127.0.0.1","$host_01","$host_02","$host_03"],"key":{"algo":"rsa","size":2048}}' | \
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=$CERT_HOME/ca-config.json -profile=server -hostname="$HOST_NAME_1,$HOST_NAME_2,$HOST_NAME_3,$host_01,$host_02,$host_03" - | \
cfssljson -bare server

((step++))
echo "### 1.$step generate Client Certification *********"
echo '{"CN":"cn5","hosts":["127.0.0.1","$host_01","$host_02","$host_03"], "key":{"algo":"rsa","size":2048}}' | \
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=$CERT_HOME/ca-config.json -profile=client -hostname="$HOST_NAME_1,$HOST_NAME_2,$HOST_NAME_3,$host_01,$host_02,$host_03" - | \
cfssljson -bare client

((step++))
echo "### 1.$step Print Certifcation *********"
# cfssl查看证书
cfssl certinfo -cert server.pem 
# cfssl查看csr文件
# cfssl certinfo -csr ca.csr

step=0

echo "*********************************************"
echo "******* 2. Operation on every NODE: *********"
echo "*********************************************"
for etcd_node_index in ${etcd_node_indeies[@]};
do
	etcd_node_name=${etcd_node_names[$etcd_node_index-1]}
	etcd_node_ip=${host_ips[$etcd_node_index-1]}
	host_name=${host_names[$etcd_node_index-1]}

	echo "### Operation on NODE:  $etcd_node_name::$etcd_node_ip::$host_name *********"
	
	let step=step+1
	echo "### 2.$step. Write ETCD config for $etcd_node_name"
	cat << EOF > ./etcd.conf
# [member]
ETCD_DATA_DIR="$ETCD_HOME/data.$etcd_node_name"
ETCD_NAME="$etcd_node_name"
ETCD_LISTEN_PEER_URLS="http://$etcd_node_ip:$peer_listen_port"
ETCD_LISTEN_CLIENT_URLS="https://$etcd_node_ip:$client_listen_port,https://127.0.0.1:$client_listen_port"

#[cluster]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://$etcd_node_ip:$peer_listen_port"
ETCD_ADVERTISE_CLIENT_URLS="https://$etcd_node_ip:$client_listen_port,https://127.0.0.1:$client_listen_port"
ETCD_INITIAL_CLUSTER="etcd-01=http://$host_01:$peer_listen_port,etcd-02=http://$host_02:$peer_listen_port,etcd-03=http://$host_03:$peer_listen_port"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster-token"
ETCD_INITIAL_CLUSTER_STATE="new"

#[security]
ETCD_TRUSTED_CA_FILE="$cacert_path"
ETCD_CERT_FILE="$cert_path"
ETCD_KEY_FILE="$keyfile_path"
EOF
	
	scp ./etcd.conf $user@$host_name:$ETCD_HOME

	((step++))
	echo "### 2.$step Copy the cert file to node"
	scp -r $CERT_HOME lorry@$host_name:$CN_SHELL

	((step++))
	echo "### 2.$step Write Systemd Service File"
	cat <<EOF > ./etcd.service
[Unit]
Description=Etcd Server
After=network.target network-online.target
Wants=network-online.target

[Service]
Type=notify
EnvironmentFile=$ETCD_HOME/etcd.conf
WorkingDirectory=$ETCD_HOME/
ExecStart=$ETCD_HOME/etcd 
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

EOF
	((step++))
	echo "### 2.$step stop etcd service"
	sshpass -p $root_password ssh root@$host_name "systemctl stop etcd.service"
	
	((step++))
	echo "### 2.$step delete data node"
	sshpass -p $root_password ssh root@$host_name "rm -rf $ETCD_HOME/data*"

	((step++))
	echo "### 2.$step systemd service file copy"
	sshpass -p $root_password scp ./etcd.service root@$host_name:/etc/systemd/system

	((step++))
	echo "### 2.$step install etcd as systemd service"
	sshpass -p $root_password ssh root@$host_name "systemctl daemon-reload"
	sshpass -p $root_password ssh root@$host_name "systemctl enable etcd.service"
	sshpass -p $root_password ssh root@$host_name "systemctl restart etcd.service"

	# echo "### 5. clear generated file"
	# rm -rf ./etcd.service
	# rm -rf ./etcd.conf

done;
echo ""
echo "### sleep 3s for waiting node ready..."
echo ""
sleep 3s

((step++))
echo "### 2.$step check status: List Member"
sshpass -p $root_password ssh root@$host_name "$ETCD_HOME/etcdctl \
--endpoints=$host_01:2379,$host_02:2379,$host_03:2379 \
--cert=$cert_path \
--key=$keyfile_path \
--cacert=$cacert_path \
--write-out=table \
member list"

((step++))
echo "### 2.$step check status: write data"
sshpass -p $root_password ssh root@$host_name "$ETCD_HOME/etcdctl \
--endpoints=$host_01:2379,$host_02:2379,$host_03:2379 \
--cert=$cert_path \
--key=$keyfile_path \
--cacert=$cacert_path \
put MY_key MY_value"

sshpass -p $root_password ssh root@$host_name "$ETCD_HOME/etcdctl \
--endpoints=$host_01:2379,$host_02:2379,$host_03:2379 \
--cert=$cert_path \
--key=$keyfile_path \
--cacert=$cacert_path \
get MY_key"
